package com.dome.server;

import com.alibaba.fastjson.JSON;
import com.dome.common.exception.DomeException;
import com.dome.common.pojo.DomeResponse;
import com.dome.common.pojo.PageResponse;
import com.dome.common.pojo.Pagination;
import com.dome.dao.entity.Dept;
import com.dome.dao.entity.DeptExample;
import com.dome.dao.entity.Tickets;
import com.dome.dao.entity.TicketsExample;
import com.dome.dao.mapper.DeptMapper;
import com.dome.dao.mapper.TicketsMapper;
import com.dome.enumeration.tickets.IndicatorEnum;
import com.dome.enumeration.tickets.OrderTypeEnum;
import com.dome.pojo.Tickets.*;
import com.dome.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TicketsServer {

    private static List<String> ORDER_TYPE_LIST = Arrays.stream(OrderTypeEnum.values()).map(OrderTypeEnum::getCode).collect(Collectors.toList());

    @Autowired
    private TicketsMapper ticketsMapper;

    @Autowired
    private DeptMapper deptMapper;

    public void addTickets(TicketsReq req) {

        //参数校验
        paramValidated(req);

        //验证工单编号是否重复
        TicketsExample example = new TicketsExample();
        TicketsExample.Criteria criteria = example.createCriteria();
        criteria.andOrderNoEqualTo(req.getOrderNo());
        List<Tickets> ticketsList = ticketsMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(ticketsList)){
            log.info("TicketsServer.addTickets 该工单信息已存在 request: {}", JSON.toJSONString(req));
            throw new DomeException("该工单信息已存在");
        }

        Tickets tickets = new Tickets();
        tickets.setOrderNo(req.getOrderNo());
        tickets.setOrderType(req.getOrderType());
        tickets.setTitle(req.getTitle());
        tickets.setContent(req.getContent());
        tickets.setCreateTime(new Date());
        tickets.setIsOverdue(req.getIsOverdue());
        ticketsMapper.insertSelective(tickets);

    }

    /**
     * 参数校验
     * @param req
     */
    private void paramValidated(TicketsReq req) {
        if (StringUtils.isEmpty(req.getOrderNo()) || StringUtils.isEmpty(req.getOrderType()) || StringUtils.isEmpty(req.getTitle())){
            log.info("TicketsServer.paramValidated 必填字段存在空 request: {}", JSON.toJSONString(req));
            throw new DomeException("必填字段存在空");
        }
        if (!ORDER_TYPE_LIST.contains(req.getOrderType())){
            log.info("TicketsServer.paramValidated 工单类型不存在 request: {}", JSON.toJSONString(req));
            throw new DomeException("工单类型不存在");
        }
    }

    /**
     * 按工单编号删除
     * @param req
     */
    public void deleteTickets(TicketsReq req) {
        if (StringUtils.isEmpty(req.getOrderNo())){
            log.info("TicketsServer.deleteTickets 工单编号不能为空 request: {}", JSON.toJSONString(req));
            throw new DomeException("工单编号不能为空");
        }
        TicketsExample example = new TicketsExample();
        TicketsExample.Criteria criteria = example.createCriteria();
        criteria.andOrderNoEqualTo(req.getOrderNo());
        ticketsMapper.deleteByExample(example);
    }

    /**
     * 按工单编号进行修改
     * @param req
     */
    public void updateTickets(TicketsReq req) {
        TicketsExample example = new TicketsExample();
        TicketsExample.Criteria criteria = example.createCriteria();
        criteria.andOrderNoEqualTo(req.getOrderNo());
        List<Tickets> ticketsList = ticketsMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(ticketsList)){
            log.info("TicketsServer.updateTickets 工单编号不存在 request: {}", JSON.toJSONString(req));
            throw new DomeException("工单编号不存在");
        }
        Tickets tickets = ticketsList.get(0);
        tickets.setOrderType(req.getOrderType());
        tickets.setTitle(req.getTitle());
        tickets.setContent(req.getContent());
        ticketsMapper.updateByPrimaryKeySelective(tickets);
    }

    /**
     * 分页查询
     * @param req
     * @return
     */
    public PageResponse<TicketsVO> queryTickets(TicketsReq req) {

        Pagination<TicketsVO> pagination = new Pagination<>();
        pagination.setPageNo(req.getPageNo());
        pagination.setPageSize(req.getPageSize());
        TicketsExample example = new TicketsExample();
        TicketsExample.Criteria criteria = example.createCriteria();
        if (StringUtils.isNoneEmpty(req.getOrderNo())){
            criteria.andOrderNoEqualTo(req.getOrderNo());
        }
        long count = ticketsMapper.countByExample(example);
        if (count == 0L){
            return PageResponse.ofPage(pagination);
        }
        RowBounds bounds = new RowBounds(req.getPageNo(), req.getPageSize());
        List<Tickets> tickets = ticketsMapper.selectByExampleWithRowbounds(example, bounds);
        List<TicketsVO> list = new ArrayList<>();
        for (Tickets ticket : tickets) {
            TicketsVO vo = new TicketsVO();
            BeanUtils.copyProperties(ticket,vo);
            vo.setOrderTypeCode(ticket.getOrderType());
            vo.setOrderTypeDesc(OrderTypeEnum.getDesc4Show(ticket.getOrderType()));
            vo.setIsOverdueCode(ticket.getIsOverdue());
            vo.setIsOverdueDesc(IndicatorEnum.getDesc4Show(ticket.getIsOverdue()));
            vo.setCreateTime(TimeUtils.date2ShortStr(req.getCreateTime()));
            vo.setFenpaiTime(TimeUtils.date2ShortStr(req.getFenpaiTime()));
            list.add(vo);
        }
        pagination.setTotalItemCount(count);
        pagination.setTotalPageCount((count + req.getPageNo() - 1) / req.getPageSize());
        pagination.setData(list);
        return PageResponse.ofPage(pagination);
    }

    /**
     *
     * @param req
     * @return
     */
    public DomeResponse<String> fenpai(ApportionReq req) {

        if (StringUtils.isEmpty(req.getHandleDeptId()) || StringUtils.isEmpty(req.getOrderNo()) || StringUtils.isEmpty(req.getDeptName())) {
            log.info("TicketsServer.fenpai 必填参数存在空 request: {}", JSON.toJSONString(req));
            throw new DomeException("必填参数存在空");
        }

        TicketsExample example = new TicketsExample();
        TicketsExample.Criteria criteria = example.createCriteria();
        criteria.andOrderNoEqualTo(req.getOrderNo());
        List<Tickets> list = ticketsMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(list)){
            log.info("TicketsServer.fenpai 工单信息不存在 request: {}", JSON.toJSONString(req));
            throw new DomeException("工单信息不存在");
        }
        Tickets tickets = list.get(0);
        if (StringUtils.isNoneEmpty(tickets.getHandleDeptId())){
            log.info("TicketsServer.fenpai 该工单已分派 request: {}", JSON.toJSONString(req));
            throw new DomeException("该工单已分派");
        }
        if (OrderTypeEnum.INVALID.getCode().equals(tickets.getOrderType())){
            log.info("TicketsServer.fenpai 无效工单，无法分派 request: {}", JSON.toJSONString(req));
            throw new DomeException("无效工单，无法分派");
        }

        //验证部门是否存在
        DeptExample deptExample = new DeptExample();
        DeptExample.Criteria deptExampleCriteria = deptExample.createCriteria();
        deptExampleCriteria.andDeptIdEqualTo(req.getHandleDeptId());
        deptExampleCriteria.andDeptNameEqualTo(req.getDeptName());
        List<Dept> depts = deptMapper.selectByExample(deptExample);
        if (CollectionUtils.isEmpty(depts)){
            log.info("TicketsServer.fenpai 分派部门不存在 request: {}", JSON.toJSONString(req));
            throw new DomeException("分派部门不存在");
        }
        tickets.setHandleDeptId(req.getHandleDeptId());
        tickets.setFenpaiTime(new Date());
        ticketsMapper.updateByPrimaryKeySelective(tickets);
        return DomeResponse.success("SUCCESS");
    }

    /**
     * 查询指定月份每天的总量、超期率
     * @param month 月份 格式 yyyy-mm-dd
     * @return
     */
    public DomeResponse<List<MonthDayTotalResp>> queryMonthDayTotal(String month) {

        if (StringUtils.isEmpty(month)){
            throw new DomeException("指定要查询的月份");
        }
        TimeUtils.formatStrToDateYm(month);
        List<MonthTicketsDTO> monthTickets = ticketsMapper.queryMonthTickets(month);
        Map<String, List<MonthTicketsDTO>> dateListMap = monthTickets.stream().collect(Collectors.groupingBy(MonthTicketsDTO::getCreateTime));
        List<MonthDayTotalResp> list = new ArrayList<>();
        for (Map.Entry<String, List<MonthTicketsDTO>> entry : dateListMap.entrySet()) {

            MonthDayTotalResp vo = new MonthDayTotalResp();
            vo.setDayTime(entry.getKey());
            vo.setTotal(entry.getValue().size());
            long count = entry.getValue().stream().filter(a -> StringUtils.isNoneEmpty(a.getIsOverdue()))
                    .filter(e -> e.getIsOverdue().equals(IndicatorEnum.Y.getCode())).count();
            vo.setExpiration(new BigDecimal(count).divide(new BigDecimal(entry.getValue().size()),2, RoundingMode.HALF_UP));
            list.add(vo);
        }
        return DomeResponse.success(list);
    }

    /**
     * 指定查询每个部门的工单总量、超期率
     * @param month
     * @return
     */
    public DomeResponse<List<MonthDayTotalResp>> queryMonthDepartmentTotal(String month) {

        if (StringUtils.isEmpty(month)){
            throw new DomeException("指定要查询的月份");
        }
        TimeUtils.formatStrToDateYm(month);
        List<MonthTicketsDTO> monthTickets = ticketsMapper.queryMonthTickets(month);
        Map<String, List<MonthTicketsDTO>> dateListMap = monthTickets.stream().collect(Collectors.groupingBy(MonthTicketsDTO::getHandleDeptId));
        List<MonthDayTotalResp> list = new ArrayList<>();
        for (Map.Entry<String, List<MonthTicketsDTO>> entry : dateListMap.entrySet()) {

            MonthDayTotalResp vo = new MonthDayTotalResp();
            vo.setDeptId(entry.getKey());
            vo.setTotal(entry.getValue().size());
            long count = entry.getValue().stream().filter(a -> StringUtils.isNoneEmpty(a.getIsOverdue()))
                    .filter(e -> e.getIsOverdue().equals(IndicatorEnum.Y.getCode())).count();
            vo.setExpiration(new BigDecimal(count).divide(new BigDecimal(entry.getValue().size()),2, RoundingMode.HALF_UP));
            list.add(vo);
        }
        return DomeResponse.success(list);

    }

    public DomeResponse<List<MonthDayTotalResp>> queryMonthOrderTypeTotal(String month) {
        if (StringUtils.isEmpty(month)){
            throw new DomeException("指定要查询的月份");
        }
        TimeUtils.formatStrToDateYm(month);
        List<MonthTicketsDTO> monthTickets = ticketsMapper.queryMonthTickets(month);
        Map<String, List<MonthTicketsDTO>> dateListMap = monthTickets.stream().collect(Collectors.groupingBy(MonthTicketsDTO::getOrderType));
        List<MonthDayTotalResp> list = new ArrayList<>();
        for (Map.Entry<String, List<MonthTicketsDTO>> entry : dateListMap.entrySet()) {

            MonthDayTotalResp vo = new MonthDayTotalResp();
            vo.setOrderType(entry.getKey());
            vo.setTotal(entry.getValue().size());
            long count = entry.getValue().stream().filter(a -> StringUtils.isNoneEmpty(a.getIsOverdue()))
                    .filter(e -> e.getIsOverdue().equals(IndicatorEnum.Y.getCode())).count();
            vo.setExpiration(new BigDecimal(count).divide(new BigDecimal(entry.getValue().size()),2, RoundingMode.HALF_UP));
            list.add(vo);
        }
        return DomeResponse.success(list);
    }
}
